Prototype Pollution
オブジェクトのプロパティアクセスに影響を与えることができる
プロトタイプとは?
JavaScriptにおける継承を実現する機構のこと
オブジェクト指向言語で言えば親クラスのようなもの
詳しくはMDNを読んでください
重要なこと
オブジェクトのプロトタイプは、obj.__proto__で取得できる
標準で非推奨の機能なので、将来削除される可能性がある
JavaScriptのプロパティアクセスは、プロトタイプに対して該当するプロパティがあるかどうか再帰的に調べて、あればその値を、無ければundefinedを返すようになっている
A -> B -> CというプロトタイプチェーンがあるときにA.fooにアクセスした場合
Aにfooというプロパティがあれば、それを返す
Aにfooというプロパティが無ければ、AのプロトタイプのBにfooというプロパティがあるか調べる
Bにfooがあればそれを、無ければBのプロトタイプのCを調べ...
基本的にオブジェクトはすべてObject.prototypeを継承している
NumberもStringもArrayもFunctionもObject.prototypeをプロトタイプチェーンに持つ
JavaScriptのプロパティアクセスはドットでも添字でもアクセスできる
a["b"]["c"]とa.b.cは等価
a["__proto__"]でプロトタイプにアクセスできる
Prototype Pollutionとは?
プロトタイプのプロパティに対して悪意のある書き込みを行い、そのオブジェクトをプロトタイプに持つ全てのオブジェクトのプロパティアクセスに対して影響を与える攻撃
obj[A][B] = Cのような処理があり、攻撃者がA,B,Cを操作できるとき典型的なPrototype Pollutionの脆弱性が生まれる
code:poc.js
const obj = {}; // プロトタイプチェーンは obj => Object.prototype => null
// 攻撃者がObject.prototype.pollutedに書き込みを行う
// 別のオブジェクトを作成する
const obj2 = {}; // プロトタイプチェーンは obj2 => Object.prototype => null
console.log(obj2.polluted); // => pwned
上書きできるのは元のオブジェクトで定義されていないプロパティだけ
code:poc.js
const obj = {hoge: "original"}; // {hoge: "original"} => Object.prototype => null
// objにhogeプロパティが存在するため、プロトタイプにさかのぼらずにobj.hogeを出力する
console.log(obj.hoge) // => "original";
定義されてないプロパティを上書きするだけで脆弱性になるの?
危険なオプションを有効にしたり、外部からの書き込みが想定されていない部分に書き込んだりすることで攻撃につなげたりできる
対策
Object.prototype.hasOwnPropertyを用いて上書きするプロパティが自分で定義したものか確認する
obj = {a: 1}のとき
Object.prototype.hasOwnProperty.call(obj, "a") === true
Object.prototype.hasOwnProperty.call(obj, "toString") === false (objで定義したものではないので)
これを使ってobj[A] = Bの前にAをチェックする
{}ではなくObject.create(null)を利用する
Object.create(null)とするとプロトタイプを持たない(プロトタイプがnullの)オブジェクトを作成できる
プロトタイプを持たないので、Object.prototypeなどを汚染できない
オブジェクトの代わりにnew Map()を使えないか考える
攻撃テクニック
obj.__proto__以外にもobj.constructor.prototypeでプロトタイプにアクセスできる
__proto__を弾くだけでは不十分
Gadgetを探す
一般に適用できるテクニックはないので、問題ごとにGadgetを探す必要があることが多い
既存のCVEや既知のgadgetを使うときもある
ソースコードやライブラリを調べてPrototype Pollutionで悪用できそうな未定義のプロパティを探す
if (A.B) { ~ }や、if (A[B]) { ~ } // Bは操作可能が狙い目
過去の例
Asian Cyber Security Challange 2021 - Cowsay as a Service
child_process.spawnSyncのoptions.shellを汚染して任意コード実行
CakeCTF 2022 - Panda Memo
テンプレートエンジンmustacheのキャッシュの汚染
MapleCTF 2022 - Viene Library
node-fetchのX-HTTP-Method-Overrideを汚染してMethodを上書き
参加者ごとにインスタンスが提供されたり、毎回インスタンスが破棄される問題はPrototype Pollution (?)
Prototype Pollutionは性質上環境を永続的に汚染するので、複数の参加者がひとつのサーバーを共有する問題を壊れないように作るのは難しい
そのためPrototype Pollutionの問題はインスタンスは破棄されたり分けられたりすることが多いので、その形式ならPrototype Pollutionだろうというジンクス
もう古いかも
資料
クライアントサイドで発見されたPrototype Pollutionと悪用できる汚染先
CTFのWebセキュリティにおけるJavaScript,nodejsまとめ(Prototype pollution, 難読化)
【1分見て】実例から学ぶprototype pollution【kurenaif勉強日記】 https://www.youtube.com/watch?v=qP8ihBctMeY
Prototype pollutionの攻撃手法に関する発表のスライド